Welcome back to get started with scripting our project, we first need to code the two scripts that
are going to be responsible for loading all the modules on the client and on the server.
The plan is to have a table in each of these scripts that keep track of all the modules that have been
loaded, initialized, and started.
The idea is that we're first going to go through and require all the module scripts necessary for the
game, on the client and on the server.
That way when we require the module scripts, it allows us to set up all of the variables and functions
for each module.
The next step would be to initialize all of the modules.
Or basically we're going to let any module script that needs to connect functions to events set themselves
up, or initialize themselves before they start executing code.
It's important that we initialize all of our scripts first.
That way they are ready to start listening to events.
We can create an initialize or init function for the modules that need to connect functions to events.
After we have initialized all of our modules, we're then going to start any that need to be started
or a.k.a any modules that need to continually run some code or functionality like a while loop or firing
events will be started using a start function in the module script.
So let's go ahead and get started.
We're first going to do the start script for the server.
So we're going to go ahead and open this up.
And the only thing we're going to need in here is to reference the server script service.
That way we can reference all of the different folders that are in our server script service.
So get service server script service.
And then we can make a reference to all of these services that are going to be in our game.
So we could do server script service, dot server dot services.
Then I'm going to create a table, I'm going to call it tracker.
And this is going to be responsible for tracking and storing all of the modules that have been loaded.
So we'll create one key value pair for loaded modules we'll have a section for initialize module.
So this will keep track of whether or not they have been initialized.
And then we're going to have a section for started modules or whether or not they've been started yet.
Then the next thing I'm going to do is I'm going to create a two private functions that are going to
override the print and warn function.
So I'm just going to call this one new print.
And it's going to take a variable number of arguments just like the regular print function.
And all we're going to do is call the print function.
And we're going to put a string in here, which is a bracket S bracket, to indicate that this message
is coming from the server.
And then we could just put a comma and pass all of the other arguments that were passed to our new print
function.
And then we could do the exact same thing, but we could do it for the warn function.
So new warn and we'll just warn again on the server whatever we want to send to this function.
Now let's go ahead and create some functions for loading, starting and initializing our modules.
So we'll have a function to uh load a module.
So we'll call this load module.
And we'll pass a module script to it.
We're going to have a function to initialize a module.
So we could call it initialize module.
And this will pass a.
Loaded module.
So we'll get the table of the module script that was loaded, as well as the name of the module script,
and you'll see why in a moment.
And then we're going to do the same thing for starting a module.
So start module we'll get this loaded module and the name of the module as well.
So basically what we're going to do down here in this main section is we're going to call our new Warn
function.
And we're going to send out a message in the console saying that we're starting up the server so we
can do something like starting server and say something like we're loading the services in our game.
So the first thing that we would do is that we loop through every single module script that is inside
of our services folder.
So we would get all of the children and our services folder.
And then what we would do is we would call the load module function and pass that module script to it.
So all of the services that are going to exist in here are going to get loaded.
And then after we've loaded all of them, then we can copy this message again and send out another warning
that we're now going to initialize modules.
So we could do initializing modules.
And then we can loop through every single loaded module that's going to be inside of the initialize
table.
So it's going to check to see what module scripts need to be initialized.
And it's going to initialize them.
So the idea is that we're going to have a module name stored in there.
And what we're going to do.
As we're going to loop through all those modules that need to be initialized, and then we'll call the
initialize module function.
And then what we're going to do is we're going to need to pass the loaded module that we can call the
initialize function within that module script.
So that means inside of our load table we're going to have it stored in here using the modules name.
And then we can just pass the name of the module itself as well.
So we'll do something like that.
And then we're going to do basically the same thing, but for starting our module.
So this section will be for starting modules.
There will be all stored inside of the start table.
And instead we need to start a module.
And then once we finally have loaded, initialized and started our modules, then we can warn one last
time that we have finished loading the server.
We could say server loading finished.
And then what I'm going to do is I'm going to set a attribute on the workspace.
So set attribute we can just call it something like server loaded.
And we're going to set this to true.
And this is to let the client know that the server has finished loading and setting up all of these
scripts.
So let's go ahead and fill out these functions right here to load a module.
The first thing I want to do is I want to calculate how long it took to load this module.
So we're going to have a start time.
And we're going to use the tick function to get the starting time.
And then we're going to use our new print function to print out into the console.
And we can say something like loading module.
And we're going to put a couple other quotations.
And then we're going to put a directive in here as a string.
And we're going to format this with the modules name.
So we're loading module for example uh Squidward service.
And then what we're going to do is we're going to use a p call and pass a function in here.
And we're going to require our module script so we can get the loaded module using the require function
and pass the module script.
And then what we could do is put inside of the load table, this module.
And we're going to create a key value pair using the modules name.
And at that key we're going to store the table that was returned from our module script.
So that way we can access it here and here and pass it to our initialize and start module functions.
The next thing we need to do is we need to check if this module script has an initialize function.
So if this loaded module inside of this table has a key for initializing or init, then what we need
to do is inside of tracker dot init.
We need to create a key value pair for this module, and we're going to set it to false, meaning it
hasn't been initialized yet, but we need to initialize it in the future.
And then we're going to do the exact same thing and check to see if this module has a start function.
If it does, then we're going to basically do the exact same thing.
We can let me actually copy this.
So instead of storing it in the initialize table we're going to do this in the start table.
And the reason I'm using a p call in this is just in case this module script we're trying to require
errors.
For some reason we don't want to halt our entire game.
We only want to have the code stop in that particular module script so we can store the result from
this function.
So success and result from this p call.
And then once we're done loading this module, then we're also going to get the end time using the tick
function.
And what we could do here is look to see if we were successful in loading our module script.
So if success then we're going to use the new print function and print out a message like uh, I'm going
to indent it with like two vertical bars and say we loaded a module and put a directive here for the
name of the module.
And we can format this with module dot name.
So we loaded this module.
And then we're going to pass a second string to our new print function.
And we can say something like it took uh we're going to put a directive here.
So we're going to do percentage point three and then F.
So we're going to put a floating point number here with a three decimal point uh accuracy.
And we're going to say it took this many seconds.
And we can format this again and pass the end time minus the start time.
So we get exactly how long it took for us to load this module script.
Otherwise, if we fail to load this module script we encountered an error.
Then what we're going to do is we're going to pass a message here using our Warn function instead.
And we're going to say something like failed to load module.
We'll pass the time.
And then what else I'm going to do is, um.
Oops.
Let me actually, uh, make sure to put these parentheses here.
But what am I going to do is I'm going to pass a backslash and then n to indicate a new line.
And I'm going to put another directive here which is going to be a string.
So percentage s.
And that means we're also going to pass the error message.
So we're going to pass the result from our Pcall function.
So if our module fails to load, it's going to tell us failed to load module like Squidward.
Service took however many seconds and then on a new line, it's going to tell us exactly what the error
was in that module script.
And that's all we need to do for our load module function.
Now what do we need to do for initializing our module script?
Well, in here, the first thing I want to check is whether or not the module that was passed to this
function has an initialize function.
If it doesn't.
So if not loaded module dot init, then we're just going to return.
That's all we want to do.
Otherwise we can print inside of the console that we are initializing a module.
So initializing module percentage s.
And we can format this with the modules name.
And actually we can move the start time up here to be in front of when we print in the console.
Because I do know that formatting a string takes a little bit of time.
So to make it more accurate.
We'll print it out first and then get the start time up here, and then we can do the same thing down
here.
So we print out we're initializing this module and I'll put more parentheses here for the name.
We'll get the start time.
And we're going to do the same thing with a P call.
So we're going to have two variables for success and results.
And all we're going to do is on this loaded module, we're going to call its init function.
And once it's done initializing, then we can set inside of tracker dot init module uh name equal to
true.
And then once that's done, we can get the end time equal to tick.
And we're basically going to do the exact same thing that we did here.
We're going to print out that we have initialized a module.
So initialized module format it with the module name say how many seconds it took.
And then if we fail to initialize it, we're going to say failed to initialize.
Module, format it with the modules name.
So module name.
How many seconds it took, and then format it with the time and the result from the P call.
And then lastly, we can do the exact same thing with our start module.
If this module does not have a start function, then we're just going to return.
Otherwise, we can again use the new print function and print out something like starting module.
Put a directive in here.
And actually let me put extra parentheses around it so we can format it.
Call the format function and pass the module name.
Another P call success result equal to p call pass a lambda function.
And in this we're going to do the same thing.
Except we're going to call the start function in the module.
And then we could just do tracker dot start pass the module name and set that key value pair to true.
Then we can get the end time.
And actually let me get the start time up here as well.
Get the start time and time, and then we can do literally the exact same thing that we did here, but
instead we're going to say started module whatever and then fail to start module.
And that's all we need to do.
So if I go ahead and run my game, uh, it should only initialize our modules because they're empty
and that's it.
It won't uh, it won't start any modules and it won't initialize any modules.
It'll just load them.
So if we go and play test or just run the game, we should see in the console that we.
Let's see.
Loaded a module.
We failed to load it because it didn't return anything because they're empty.
Loaded module list failed to load it because it didn't return anything.
And then initializing modules is empty along with starting modules.
And then we finished loading the server.
Very cool.
Now the fun part about this is we can literally just copy all of the code that we've done in here.
So copy all of it.
And we're going to go to our local script.
And we're just going to paste it all in here.
And we're just going to make a couple changes.
So we can't require the server script service.
So instead what we need to require is the player service.
So we could do players get service players.
And then to get access to all of the handlers on the client I'll rename this to handlers.
We're just going to get players dot local player access our player scripts folder and then access the
client folder.
And inside of there the handlers folder.
And I do not need to use wait for child because this script is only going to execute once everything
has been replicated.
And of course the script is only going to execute once it's actually part of the player instance.
So all of this stuff is going to be loaded.
I don't have to use wait for child on it at all.
We're going to have the exact same tracker table in here.
And I'm going to rename this with C.
So we know this is being printed on the client.
We'll basically do the exact same thing for loading the module, initializing a module, and starting
a module.
And then what we could do instead is just get all of the module scripts in our handlers folder, load
it, initialize them and start them.
And we can just change these words here to starting client.
And loading handlers.
Initializing modules starting modules.
And then we can say client loading finished.
And we can set the attribute on the workspace that we have loaded the client successfully.
However, before we load the client, we need to make sure that the server is loaded first.
So inside of our main section here before we do anything, if in the workspace we get the attribute
server loaded and it's false or it doesn't exist yet, then we need to wait for the server to load so
we can do workspace, get attribute changed signal, and we're going to wait for the server to load.
And that's it.
So once the server is loaded, then we can start up the client and we should be good to go.
So that means if we play test our game.
So if we do play.
Of course we're going to see that the server loaded and started up, loaded the modules, blah blah,
blah.
And then once the server loading finished, then we started the client and required all those modules.
Very cool.
So this is exactly how we are going to organize the scripts in our game.
We're going to have modules that have their own purpose for a specific thing on the client and server,
and we'll have a section for any modules that need to be shared between other services and handlers.
So if any of these handlers or services in here need to access some shared code, they can access them
in the modules folder.
And if any services or handlers need to communicate with another service or handler, then they're going
to do that through bindable events.
Other than that, we have the client and server loading set up.
And this is exactly how we are going to structure out our horror game.
See you in the next one.